//
//  MMGVideoPrizeClawViewModel.m
//  MyApp
//
//  Created by Don on 2017/9/1.
//  Copyright © 2017年 com.memego. All rights reserved.
//

#import "MMGVideoPrizeClawViewModel.h"
#import "NSString+Replacement.h"
#include "MMGPrizeClawGameControlHandler.hpp"
#import "MMGConstSocketMsgKey.h"
#import "MMGConstSocketMsgType.h"

void onGameControlMessageDidReceive (void *ref,const char* command, const char* data, int code) {
    if (ref == NULL) {
        return;
    }
    MMGVideoPrizeClawViewModel *pcVM = (__bridge MMGVideoPrizeClawViewModel *)ref;
    @synchronized(pcVM) {
        
        NSDictionary *message = @{kMMG_SOCKET_MSG_CODE:@(code),
                                  kMMG_SOCKET_MSG_TYPE:[NSString stringWithUTF8String:command],
                                  kMMG_SOCKET_MSG_DATA:[NSString stringWithUTF8String:data],
                                  };
        DLog(@"on game control msg %@",message);
        MMGSocketMsgModel *msg = [MMGSocketMsgModel modelFromDataJson:message];
        [pcVM onSocketDidRececiveMessage:msg];
    }
}

@interface MMGVideoPrizeClawViewModel ()
//@property (nonatomic, strong) MMGSocketClient *sockeClient;
@property (nonatomic, strong) RACSubject *gameStartSignal;
@property (nonatomic, strong) RACSubject *onGameMsgDidReceiveSignal;
@property (nonatomic, strong) RACSubject *onGameStateDidChageSignal;
@property (nonatomic, strong) RACSubject *onDeviceStateDidChangeSignal;

@property (strong , nonatomic) RACSubject *timeOut2CloseSignal;

@property (nonatomic, strong) NSString *currentGameID;
@property(nonatomic, assign)EMMMGVideoPrizeClawViewState vpcvState;

@end

@implementation MMGVideoPrizeClawViewModel {
    dispatch_source_t _ctimer;
}

- (instancetype)init {
    if ((self = [super init])) {
        MMGPrizeClawGameControlHandler::getInstance()->registerGameControlMessageDidReceiveCallBackFunction((__bridge void *)self, onGameControlMessageDidReceive);
    }
    return self;
}
#pragma mark - public
- (void)starSocket {
    //TODO: - register socket msg notification
//    [self socketMsgNotificationRegister];
//    
//    [self.sockeClient connectServerHost:kSERVICE_HOST port:2005];
    int port = 2005;
    MMGPrizeClawGameControlHandler::getInstance()->gameprotoSendmessage(kMMG_SOCKET_MSG_CONNECT, kSERVICE_HOST, port);
    
}
- (void)closeSocket {
//    [self.sockeClient closeSocket];
//    [[NSNotificationCenter defaultCenter] removeObserver:self];
    int delaySec = 30;
    MMGPrizeClawGameControlHandler::getInstance()->gameprotoSendmessage(kMMG_SOCKET_MSG_QUITGAME, NULL, delaySec);
}

- (void)sendConnectDeviceWithPrizeId:(NSString *)prizeId {
//    [self.sockeClient sendConnectDeviceWithPrizeId:prizeId];
    MMGPrizeClawGameControlHandler::getInstance()->gameprotoSendmessage(kMMG_SOCKET_MSG_CONNECT_DEVICE, prizeId, 0);
    
}

- (void)sendUserAuthoMsg:(NSString *)authoCode {
//    [self.sockeClient sendUserAuthoMsg:authoCode];
    MMGPrizeClawGameControlHandler::getInstance()->gameprotoSendmessage(kMMG_SOCKET_MSG_USER_LOGIN, authoCode, 0);
}
- (void)sendGameReserveMsg {
//    [self.sockeClient sendGameReserveMsg];
    MMGPrizeClawGameControlHandler::getInstance()->gameprotoSendmessage(kMMG_SOCKET_MSG_RESERVE_GAME, NULL, 0);
}
- (void)sendGameStartMsg:(NSString *)limitTime {
//    [self.sockeClient sendGameStartMsg:limitTime];
    MMGPrizeClawGameControlHandler::getInstance()->gameprotoSendmessage(kMMG_SOCKET_MSG_START_GAME, limitTime, 0);
}

- (void)sendPrizeClawMachineControlMsgWith:(float)radian {
    GAME_CONTROLS direction = GAME_CONTROLS::CTRL_NONE;
    
    if (fabs(radian) < 0.39) {
        direction = GAME_CONTROLS::CTRL_RIGHT;
    }else if (fabs(radian) > 2.74) {
        direction = GAME_CONTROLS::CTRL_LEFT;
    }else if (fabs(radian) > 1.17 && fabs(radian) < 1.96) {
        
        if (radian < 0) {
            direction = GAME_CONTROLS::CTRL_UP;
        }else {
            direction = GAME_CONTROLS::CTRL_DOWN;
        }
    
    }else if (fabs(radian) >= 1.96  && fabs(radian) <= 2.74) {
        if (radian < 0) {
            direction = GAME_CONTROLS::CTRL_UP_LEFT;
        }else {
            direction = GAME_CONTROLS::CTRL_DOWN_LEFT;
        }
    }else if (fabs(radian) >= 0.39 && fabs(radian) <= 1.17) {
        if (radian < 0) {
            direction = GAME_CONTROLS::CTRL_UP_RIGHT;
        }else {
            direction = GAME_CONTROLS::CTRL_DOWN_RIGHT;
        }
    }
    
    //中心点是 不咗操作
    if (!fabs(radian)) {
        direction = GAME_CONTROLS::CTRL_NONE;
    }
//    DLog(@"radian :%f direction : %@",radian,direction);
    if (direction != GAME_CONTROLS::CTRL_NONE) {
        direction = [self transfDirection:direction channel:self.cameraChannel];
//        [self.sockeClient sendPrizeClawMachineControlMsgWith:direction];
        MMGPrizeClawGameControlHandler::getInstance()->gameprotoSendcontrol(direction, NULL);
    }
    
}

- (GAME_CONTROLS)transfDirection:(GAME_CONTROLS)direction channel:(int)channel {
    GAME_CONTROLS fDirection = direction;
    switch (channel) {
        case 1:
        {
         
            switch (fDirection) {
                case GAME_CONTROLS::CTRL_RIGHT:
                    fDirection = GAME_CONTROLS::CTRL_UP;
                    break;
                case GAME_CONTROLS::CTRL_LEFT:
                    fDirection = GAME_CONTROLS::CTRL_DOWN;
                    break;
                case GAME_CONTROLS::CTRL_UP:
                    fDirection = GAME_CONTROLS::CTRL_LEFT;
                    break;
                case GAME_CONTROLS::CTRL_DOWN:
                    fDirection = GAME_CONTROLS::CTRL_RIGHT;
                    break;
                case GAME_CONTROLS::CTRL_UP_LEFT:
                    fDirection = GAME_CONTROLS::CTRL_DOWN_LEFT;
                    break;
                case GAME_CONTROLS::CTRL_DOWN_LEFT:
                    fDirection = GAME_CONTROLS::CTRL_DOWN_RIGHT;
                    break;
                case GAME_CONTROLS::CTRL_UP_RIGHT:
                    fDirection = GAME_CONTROLS::CTRL_UP_LEFT;
                    break;
                case GAME_CONTROLS::CTRL_DOWN_RIGHT:
                    fDirection = GAME_CONTROLS::CTRL_UP_RIGHT;
                    break;
                    
                default:
                    fDirection = GAME_CONTROLS::CTRL_NONE;
                    break;
            }
//            if ([fDirection isEqualToString:kMMG_SOCKET_MSG_CONTROL_RIGHT]) {
//                fDirection = kMMG_SOCKET_MSG_CONTROL_UP;
//            }else if ([fDirection isEqualToString:kMMG_SOCKET_MSG_CONTROL_LEFT]) {
//                fDirection = kMMG_SOCKET_MSG_CONTROL_DOWN;
//            }else if ([fDirection isEqualToString:kMMG_SOCKET_MSG_CONTROL_UP]) {
//                fDirection = kMMG_SOCKET_MSG_CONTROL_LEFT;
//            }else if ([fDirection isEqualToString:kMMG_SOCKET_MSG_CONTROL_DOWN]) {
//                fDirection = kMMG_SOCKET_MSG_CONTROL_RIGHT;
//            }else if ([fDirection isEqualToString:kMMG_SOCKET_MSG_CONTROL_UP_LEFT]) {
//                fDirection = kMMG_SOCKET_MSG_CONTROL_DOWN_LEFT;
//
//            }else if ([fDirection isEqualToString:kMMG_SOCKET_MSG_CONTROL_DOWN_LEFT]) {
//                fDirection = kMMG_SOCKET_MSG_CONTROL_DOWN_RIGHT;
//            }else if ([fDirection isEqualToString:kMMG_SOCKET_MSG_CONTROL_UP_RIGHT]) {
//                fDirection = kMMG_SOCKET_MSG_CONTROL_UP_LEFT;
//            }else if ([fDirection isEqualToString:kMMG_SOCKET_MSG_CONTROL_DOWN_RIGHT]) {
//                fDirection = kMMG_SOCKET_MSG_CONTROL_UP_RIGHT;
//            }
            
        }
            break;
            
        default:
            break;
            
    }
    
    return fDirection;
}

- (void)sendStartClawMsg {
//    [self.sockeClient sendStartClawMsg];
    //CTRL_DOWN_CLAW
    //TODO:- 需要填入流水号
    if (!NSStringIsNullOrEmpty(self.currentGameID)) {
        MMGPrizeClawGameControlHandler::getInstance()->gameprotoSendcontrol(GAME_CONTROLS::CTRL_DOWN_CLAW, self.currentGameID);
    }else {
    
        MMGPrizeClawGameControlHandler::getInstance()->gameprotoSendmessage(kMMG_SOCKET_MSG_DOWN_CLAW, NULL, 0);
    }
}

- (void)sendWinPrizeMsg {
//    [self.sockeClient sendWinPrizeMsg];
//    MMGPrizeClawGameControlHandler::getInstance()->gameprotoSendmessage(kMMG_SOCKET_MSG_WIN_PRIZE_ACK, NULL, 0);
}

- (void)sendIAPTransactionReceipt:(NSString *)transReceipt {
//    [self.sockeClient sendInAppPurchaseTransMsgWith:transReceipt];
    
    // Create NSData object
    NSData *nsdata = [transReceipt
                      dataUsingEncoding:NSUTF8StringEncoding];
    // Get NSString from NSData object in Base64
    NSString *base64Encoded = [nsdata base64EncodedStringWithOptions:0];
    
    MMGPrizeClawGameControlHandler::getInstance()->gameprotoSendmessage(kMMG_SOCKET_MSG_IAP_PAY, base64Encoded, 0);
}


- (void)startCountDownWithTimeSec:(int)sec counting:(void (^)(int))countingCallback overCount:(void (^)(int))timeOutCallback {
    DLog(@"startCountDownWithTimeSec ");
    if (_ctimer) {
        dispatch_source_cancel(_ctimer);
        _ctimer = nil;
    }
    __block int timeout=sec; //倒计时时间
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    _ctimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0,queue);
    dispatch_source_set_timer(_ctimer,dispatch_walltime(NULL, 0),1.0*NSEC_PER_SEC, 0); //每秒执行
    dispatch_source_set_event_handler(_ctimer, ^{
        if(timeout<=0){ //倒计时结束，关闭
            dispatch_source_cancel(_ctimer);
            _ctimer = nil;
            dispatch_async(dispatch_get_main_queue(), ^{
                //设置界面的按钮显示 根据自己需求设置
                if (timeOutCallback) {
                    timeOutCallback(0);
                }
            });
        }else{
            dispatch_async(dispatch_get_main_queue(), ^{
                //设置界面的按钮显示 根据自己需求设置
                if (countingCallback) {
                    countingCallback(timeout);
                }
            });
            timeout--;
            
        }
    });
    dispatch_resume(_ctimer);
}

- (void)stopCountDown {
    if (_ctimer) {
        dispatch_source_cancel(_ctimer);
        _ctimer = nil;
    }
}


#pragma mark - private

- (void)onSocketDidRececiveMessage:(MMGSocketMsgModel *)sockekMsg {
//    MMGSocketMsgModel *sockekMsg = (MMGSocketMsgModel *)notify.object;
    if ([sockekMsg isKindOfClass:[MMGSocketMsgModel class]]) {
        DLog(@"socket msg %@",sockekMsg);
        [self.onGameMsgDidReceiveSignal sendNext:sockekMsg];
//        if (sockekMsg.code == 0)
        
        {
            DLog(@"------------------------------- currentMsgType %d -------",sockekMsg.type);
            switch (sockekMsg.type) {
                case EMMMGSocketMsgAckTypeSocketConnected: {
                    [self sendConnectDeviceCommond:sockekMsg];
                }
                    break;
                case EMMMGSocketMsgAckTypeLogin: {
                    DLog(@"user did login ...");
                    //用户登入授权完成，开始连接设备
                    [self handleLoginAckMsg:sockekMsg];

                }
                    break;
                case EMMMGSocketMsgAckTypeConnectedDevice: {
                    DLog(@"device did connect ...");
                    //激活按钮，需要预约游戏
                    [self handleConnectedDeviceAckMsg:sockekMsg];
                }
                    break;
                case EMMMGSocketMsgAckTypeReserveGame: {
                    DLog(@"预约成功并准备游戏 ....");
                    //预约成功，预约成功后服务器会返回游戏准备，如果不成功需要重新预约（激活预约按钮）
                    [self handleReserveGameAckMsg:sockekMsg];
                }
                    break;
                case EMMMGSocketMsgAckTypeReadyStartGame: {
                    //游戏准备完成 ，激活开始游戏按钮
                    DLog(@"游戏准备完成 ....");
                    [self handleReadyGameAckMsg:sockekMsg];
                    
                    
                }
                    break;
                case EMMMGSocketMsgAckTypeStartGame: {
                    //成功开始游戏，激活摇杆和下爪按钮
                    DLog(@"开始游戏 ....");
                    [self handleStartGameAckMsg:sockekMsg];
                }
                    break;
                case EMMMGSocketMsgAckTypeControlDevice: {
                    [self handleControlDeviceAckMsg:sockekMsg];
                }
                    break;
                    
                case EMMMGSocketMsgAckTypeDownClaw: {
                    DLog(@"下爪指令发送成功 ...");
                    [self handleDownClawAckMsg:sockekMsg];
                }
                    break;
                case EMMMGSocketMsgAckTypeWinPraize://已经过期
                case EMMMGSocketMsgAckTypeWinPraizeAck: {
                    DLog(@"成功抓取娃娃 ...");
                    [self handleWinPraizeAckMsg:sockekMsg];
                    
                }
                    break;
                case EMMMGSocketMsgAckTypeUserAccessAmount:{
                    DLog(@"用户余额 ...");
                    self.userRemaindCoin = [sockekMsg.data intValue];
                }
                break;
                case EMMMGSocketMsgAckTypeCancelGame:{
                    DLog(@"取消游戏 ...");
                }
                break;
                case EMMMGSocketMsgAckTypeDeviceStatistics:{
                    DLog(@"统计 ...%@",sockekMsg.data);
                    
                    NSArray *params = [sockekMsg.data componentsSeparatedByString:@"|"];
                    //观看人数
                    self.visiteCount=[[params mg_objectAtIndex:0] intValue];
                    //预约人数
                    self.reserveCount=[[params mg_objectAtIndex:1] intValue];
                    //机器当前的游戏状态，暂时乎略
                    self.gameCurrentStatus=[params mg_objectAtIndex:2];
                }
                    break;
                case EMMMGSocketMsgAckTypeHeartbeat: {
                    DLog(@"这是心跳 .....");
                }
                    break;
                
                default:
                    break;
            }
        }
//        else {
//            DLog(@"error with msg :%@",sockekMsg.data);
//        }
       
     
    }

}

#pragma socket msg handler
- (void)sendConnectDeviceCommond:(MMGSocketMsgModel *)msgModel {
    if (msgModel.code == 1) {
        NSString *connectData = [NSString stringWithFormat:@"%@|%@",[MMGGameSYSSettings sharedMMGGameSYSSettings].productId,[MMGGameSYSSettings sharedMMGGameSYSSettings].userAuthCode];
//        [self sendUserAuthoMsg:[MMGGameSYSSettings sharedMMGGameSYSSettings].userAuthCode];
        [self sendConnectDeviceWithPrizeId:connectData];
    }else {
        DLog(@"error code:%d  msg :%@",msgModel.code,msgModel.data);
    }
}

- (void)handleLoginAckMsg:(MMGSocketMsgModel *)msgModel {
    if (msgModel.code == 0) {
//        [self sendConnectDeviceWithPrizeId:[MMGGameSYSSettings sharedMMGGameSYSSettings].productId];
    }else {
        DLog(@"error code:%d  msg :%@",msgModel.code,msgModel.data);
    }
}

- (void)handleConnectedDeviceAckMsg:(MMGSocketMsgModel *)msgModel {
    if (msgModel.code == 0) {
        DLog(@"curretn device id %@ ",msgModel.data);
        [MMGGameSYSSettings sharedMMGGameSYSSettings].deviceId = msgModel.data;
//        self.deviceConnectState = EMMMGPrizeClawDeviceStateConnected;
        [self.onDeviceStateDidChangeSignal sendNext:@(EMMMGPrizeClawDeviceStateConnected)];
        //连接、重连
        if (self.vpcvState != EMMMGVideoPrizeClawViewStateJoystick) {
            //连接时激活预约按钮、重连不需要设置
            self.vpcvState = EMMMGVideoPrizeClawViewStateStartGame;
        }
        [self.onGameStateDidChageSignal sendNext:@(self.vpcvState)];
    }else {
        DLog(@"error code:%d  msg :%@",msgModel.code,msgModel.data);
    }

}


/**
 处理激活命令返回信息
 
 预约成功，预约成功后服务器会返回游戏准备，如果不成功需要重新预约（激活预约按钮）
 
 @param msgModel 激活命令返回信息
 */
- (void)handleReserveGameAckMsg:(MMGSocketMsgModel *)msgModel {
    if (msgModel.code == 0) {
        self.vpcvState = EMMMGVideoPrizeClawViewStateOrderGame;
        [self.onGameStateDidChageSignal sendNext:@(self.vpcvState)];
        DLog(@"error code:%d  msg :%@",msgModel.code,msgModel.data);
    }else {
        self.vpcvState = EMMMGVideoPrizeClawViewStateStartGame;
        [self.onGameStateDidChageSignal sendNext:@(self.vpcvState)];
        DLog(@"error code:%d  msg :%@",msgModel.code,msgModel.data);
    }
}

- (void)handleReadyGameAckMsg:(MMGSocketMsgModel *)msgModel {
    if (msgModel.code == 0) {
        //游戏准备完成，激活开始游戏按钮
        self.vpcvState = EMMMGVideoPrizeClawViewStateStartGame;
        
        self.gameTimeOut = [msgModel.data intValue];
    }else {
        DLog(@"error code:%d  msg :%@",msgModel.code,msgModel.data);
        self.vpcvState = EMMMGVideoPrizeClawViewStateOrderGame;
//        [SVProgressHUD showErrorWithStatus:msgModel.data];
    }
    [self.onGameStateDidChageSignal sendNext:@(self.vpcvState)];
    
}
- (void)handleStartGameAckMsg:(MMGSocketMsgModel *)msgModel {
    if (msgModel.code == 0) {
        //成功开始游戏，激活摇杆和下爪按钮
        self.vpcvState = EMMMGVideoPrizeClawViewStateJoystick;
        [self.onGameStateDidChageSignal sendNext:@(self.vpcvState)];
        
        
        NSArray *params = [msgModel.data componentsSeparatedByString:@"|"];
        //时间
        int timeOut =[[params mg_objectAtIndex:0] intValue];
        //当局游戏ID
        NSString *gameID= [params mg_objectAtIndex:1];
        self.currentGameID = gameID;
        
        self.gameTimeOut = timeOut;
        
    }else {
        DLog(@"error code:%d  msg :%@",msgModel.code,msgModel.data);
    }

}
- (void)handleControlDeviceAckMsg:(MMGSocketMsgModel *)msgModel {
    if (msgModel.code == 0) {
//        self.gameTimeOut = [msgModel.data intValue];
    }else {
        DLog(@"error code:%d  msg :%@",msgModel.code,msgModel.data);
    }
}
- (void)handleDownClawAckMsg:(MMGSocketMsgModel *)msgModel {
    if (msgModel.code == 0) {
        self.vpcvState = EMMMGVideoPrizeClawViewStateClawAck;
        [self.onGameStateDidChageSignal sendNext:@(self.vpcvState)];
    }else {
        DLog(@"error code:%d  msg :%@",msgModel.code,msgModel.data);
    }
}

- (void)handleWinPraizeAckMsg:(MMGSocketMsgModel *)msgModel {
    DLog(@"code:%d  msg :%@",msgModel.code,msgModel.data);
    [self sendWinPrizeMsg];
    self.vpcvState = EMMMGVideoPrizeClawViewStateOrderGame;
    [self.onGameStateDidChageSignal sendNext:@(self.vpcvState)];
    
    if (msgModel.code == 0) {
//        [SVProgressHUD showSuccessWithStatus:msgModel.data];
    }else {
//        [SVProgressHUD showErrorWithStatus:msgModel.data];
        DLog(@"error code:%d  msg :%@",msgModel.code,msgModel.data);
    }
}

//- (MMGSocketClient *)sockeClient {
//    if (!_sockeClient) {
//        _sockeClient = [[MMGSocketClient alloc] init];
//    }
//
//    return _sockeClient;
//}

- (RACSubject *)gameStartSignal {
    if (!_gameStartSignal) {
        _gameStartSignal = [RACSubject subject];
    }
    
    return _gameStartSignal;
}

- (RACSubject *)onGameMsgDidReceiveSignal {
    if (!_onGameMsgDidReceiveSignal) {
        _onGameMsgDidReceiveSignal = [RACSubject subject];
    }
    return _onGameMsgDidReceiveSignal;
}
- (RACSubject *)onGameStateDidChageSignal {
    if (!_onGameStateDidChageSignal) {
        _onGameStateDidChageSignal = [RACSubject subject];
    }
    return _onGameStateDidChageSignal;
}

- (RACSubject *)onDeviceStateDidChangeSignal {
    if (!_onDeviceStateDidChangeSignal) {
        _onDeviceStateDidChangeSignal = [RACSubject subject];
    }
    return _onDeviceStateDidChangeSignal;
}

- (RACSubject *)timeOut2CloseSignal {
    if (!_timeOut2CloseSignal) {
        _timeOut2CloseSignal = [RACSubject subject];
    }
    
    return _timeOut2CloseSignal;
}

@end
